package io.xxx.eva.robot;

import io.xxx.eva.robot.send.IPadSender;
import io.xxx.eva.robot.send.PhoneSender;
import io.xxx.eva.robot.send.limit.MessageLimiter;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import java.util.List;

@Slf4j
@Component
public class TalkerFactory implements ApplicationRunner, ApplicationContextAware {

    @Autowired
    private RobotRepository robotRepository;

    @Autowired
    private GenericApplicationContext applicationContext;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private List<MessageLimiter> limiters;

    @Autowired
    private IPadSender iPadSender;

    @Autowired
    private PhoneSender phoneSender;

    public Talker getTalker(Robot robot) {
        return applicationContext.getBean(getBeanName(robot), Talker.class);
    }

    @Override
    public synchronized void run(ApplicationArguments args) {
        log.info("机器人启动开始");
        List<Robot> robots = robotRepository.findAll();
        for (Robot robot : robots) {
            RRateLimiter speedRateLimiter = redissonClient.getRateLimiter("RB:" + robot.getId() + ":RL:SM");
            speedRateLimiter.setRate(RateType.OVERALL, 1, 1, RateIntervalUnit.SECONDS);
            BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Talker.class)
                    .addConstructorArgValue(speedRateLimiter)
                    .addConstructorArgValue(limiters)
                    .addConstructorArgValue(iPadSender)
                    .addConstructorArgValue(phoneSender)
                    .addConstructorArgValue(true)
                    .getBeanDefinition();
            String beanName = getBeanName(robot);
            applicationContext.registerBeanDefinition(beanName, beanDefinition);
            Talker talker = applicationContext.getBean(beanName, Talker.class);

            new Thread(talker).start(); // TODO 需要使用协程降低CPU和Memory的消耗 Thread.startVirtualThread(talker);
        }
        log.info("机器人启动完毕");
    }

    private String getBeanName(Robot robot) {
        return "talker_" + robot.getId();
    }

    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = (GenericApplicationContext) applicationContext;
    }
}
